home *** CD-ROM | disk | FTP | other *** search
- /*
- 94/01/05 aih
- - added pre-event task list
-
- 94/01/02 aih
- - uses PointerFixedLib to allocate the event structures, which is more
- efficient than using the memory manager (I don't use handles since
- they'd be less efficient than pointers)
-
- 93/12/17 aih
- - changed to use LLPtrLib to avoid duplicating linked-list code
-
- 93/10/18 aih
- - major revisions to support new event handling method
- - added focuslist to windows
-
- 93/03/12 Ari Halberstadt (AIH)
- - Split into a separate file from EventLib and WindowLib */
-
- #include "EventPrivateLib.h"
- #include "PointerFixedLib.h"
- #include "WindowLib.h"
-
- /*----------------------------------------------------------------------------*/
- /* validation */
- /*----------------------------------------------------------------------------*/
-
- /* true if the object is valid */
- Boolean EventObjectValid(EventObjectType object)
- {
- return(true);
- }
-
- /* true if the event item is valid */
- Boolean EventValid(EventType *event)
- {
- if (! PtrFixedValidSize(event, sizeof(EventType))) return(false);
- if (! event->table) return(false);
- if (! EventObjectValid(event->object)) return(false);
- return(true);
- }
-
- /*----------------------------------------------------------------------------*/
- /* maintaining object focus */
- /*----------------------------------------------------------------------------*/
-
- static WindowPtr gFocusWindow = NULL;
-
- /* set the object with the input focus */
- void FocusSet(EventObjectType object)
- {
- EventType *focus = NULL;
- EventType *unfocus = NULL;
-
- require(WinValid(FocusWindow()));
- unfocus = WinFocus(FocusWindow());
- WinFocusSet(FocusWindow(), object);
- focus = WinFocus(FocusWindow());
- if (focus != unfocus) {
- if (unfocus) EventFocus(unfocus, false);
- if (focus) EventFocus(focus, true);
- EventAdjustMenu();
- }
- }
-
- /* set window with input focus */
- void FocusWindowSet(WindowPtr window)
- {
- gFocusWindow = window;
- }
-
- /* return window with input focus */
- WindowPtr FocusWindow(void)
- {
- return(gFocusWindow);
- }
-
- /* return first object in focus window's object list */
- EventType *FocusList(void)
- {
- return(FocusWindow() ? WinObjects(FocusWindow()) : NULL);
- }
-
- /* return event object with input focus */
- static EventType *FocusEvent(void)
- {
- return(FocusWindow() ? WinFocus(FocusWindow()) : NULL);
- }
-
- /* return object with input focus */
- EventObjectType FocusObject(void)
- {
- return(FocusEvent() ? FocusEvent()->object : NULL);
- }
-
- /* return id of object with input focus */
- EventIDType FocusID(void)
- {
- return(FocusEvent() ? FocusEvent()->id : 0);
- }
-
- /* return event handler table of object with input focus */
- const EventTableType *FocusTable(void)
- {
- return(FocusEvent() ? FocusEvent()->table : NULL);
- }
-
- /*----------------------------------------------------------------------------*/
- /* maintaining event lists */
- /*----------------------------------------------------------------------------*/
-
- /* find the object with the specified id */
- EventType *EventFindID(EventType *list, EventIDType id)
- {
- while (list && list->id != id)
- list = EventNext(list);
- return(list);
- }
-
- /* find the object and return previous item as well */
- static void EventFindObjectPrevious(EventType *list, EventObjectType object,
- EventType **item, EventType **previous)
- {
- register EventType *p;
-
- require(! list || EventValid(list));
- require(EventObjectValid(object));
- *previous = NULL;
- for (p = list; p; p = EventNext(p)) {
- if (p->object == object)
- break;
- *previous = p;
- }
- *item = p;
- }
-
- /* find the object */
- EventType *EventFindObject(EventType *list, EventObjectType object)
- {
- while (list && list->object != object)
- list = EventNext(list);
- return(list);
- }
-
- /* insert the object before the head of the list */
- EventType *EventInsert(EventType *list, EventObjectType object,
- const EventTableType *table)
- {
- EventType *new = NULL;
-
- require(! list || EventValid(list));
- require(EventObjectValid(object));
- new = PtrFixedBegin(sizeof(EventType));
- memclr(new, sizeof(EventType));
- new->object = object;
- new->table = table;
- check(new->table != NULL);
- ensure(EventValid(new));
- return(LLPInsert(list, new));
- }
-
- /* append the object after the tail of the list */
- EventType *EventAppend(EventType *list, EventObjectType object,
- const EventTableType *table)
- {
- return(LLPAppend(list, EventInsert(NULL, object, table)));
- }
-
- /* delete the object from the list */
- EventType *EventDelete(EventType *list, EventObjectType object)
- {
- EventType *item, *previous;
-
- EventFindObjectPrevious(list, object, &item, &previous);
- list = LLPDeleteFast(list, item, previous);
- PtrFixedEnd(item);
- return(list);
- }
-
- /* move object to head of list */
- EventType *EventMoveToFront(EventType *list, EventObjectType object)
- {
- EventType *item, *previous;
-
- EventFindObjectPrevious(list, object, &item, &previous);
- return(LLPInsert(LLPDeleteFast(list, item, previous), item));
- }
-
- /*----------------------------------------------------------------------------*/
- /* using the event table which stores the event handlers for each type of
- object */
- /*----------------------------------------------------------------------------*/
-
- #define MAX_EVENT (64)
-
- static struct {
- const EventTableType *table[MAX_EVENT];
- short ntables;
- } gEventTable;
-
- /* Register the object's event handlers into the event function table.
- The table must be a pointer to permanent memory, e.g., static
- or allocated in the heap. */
- void EventTableRegister(const EventTableType *table)
- {
- require(gEventTable.ntables < MAX_EVENT);
- gEventTable.table[gEventTable.ntables++] = table;
- }
-
- /* return number of event tables */
- short EventTableCount(void)
- {
- return(gEventTable.ntables);
- }
-
- /* return the i'th event table */
- const EventTableType *EventTableGet(short i)
- {
- require(0 <= i && i < gEventTable.ntables);
- return(gEventTable.table[i]);
- }
-
- /*----------------------------------------------------------------------------*/
- /* There are two task lists: one is executed before the next event
- is retrieved, the other is executed after each event has been processed.
- The order of execution of tasks in a particular task list is unspecified.
- Once installed, tasks are executed until they are removed from the task list.
- For tasks that execute only once, you will typically remove the task from
- within the task handler (the task delete function can be called at any
- time).
-
- Since it is not always possible to predict exactly when a task handler
- will be executed (for instance, if an exception occurs during the
- processing of an event), care must be taken to ensure that the object
- processed by the task is still in existence when the task is executed.
- One way to achieve this is to add a task field to the object and set that
- field to the task handle returned by the task insert function. In the
- object's disposal routine, simply call the task delete function before
- disposing of the object. Since the task will have been deleted, it will
- no longer be executed, and there is no possibility of using the disposed
- object in the task. */
- /*----------------------------------------------------------------------------*/
-
- static TaskHandle gEventPreTasks; /* tasks executed before the next event */
- static TaskHandle gEventPostTasks; /* tasks executed after the next event */
-
- TaskHandle EventPreTaskInsert(TaskActionType action, void *data)
- {
- gEventPreTasks = TaskInsert(gEventPreTasks, action, data);
- return(gEventPreTasks);
- }
-
- void EventPreTaskDelete(TaskHandle task)
- {
- gEventPreTasks = TaskDelete(gEventPreTasks, task);
- }
-
- void EventPreTasksExecute(void)
- {
- TasksExecute(gEventPreTasks);
- }
-
- TaskHandle EventPostTaskInsert(TaskActionType action, void *data)
- {
- gEventPostTasks = TaskInsert(gEventPostTasks, action, data);
- return(gEventPostTasks);
- }
-
- void EventPostTaskDelete(TaskHandle task)
- {
- gEventPostTasks = TaskDelete(gEventPostTasks, task);
- }
-
- void EventPostTasksExecute(void)
- {
- TasksExecute(gEventPostTasks);
- }
-